From 93c71e4ff6d9a7e4bddcddad1bdbfc6ef7d7caae Mon Sep 17 00:00:00 2001 From: robertl Date: Thu, 27 Feb 2003 19:06:19 +0000 Subject: [PATCH] From Ron Parker: 1) upgrades the XML time parser to be more robust. It now recognizes and correctly parses non-Zulu timestamps and timestamps with fractional seconds (which are truncated rather than rounded, but a motivated coder with time on his hands could change that.) 2) adds a field "exported" to struct geocache_data and fills it in with the appropriate value (the value from the groundspeak:exported tag on the waypoint if one exists, else the timestamp from the gpx/time element.) 3) adds (or replaces) the groundspeak:exported tag on output for any waypoint that contains a groundspeak:cache element. 4) adds the gpx/time element to any output GPX file, using the current time. 5) modifies the duplicate filter to prefer throwing away waypoints with older or unspecified "exported" dates over those with newer dates. --- gpsbabel/defs.h | 1 + gpsbabel/duplicate.c | 35 +++++++++++- gpsbabel/gpx.c | 131 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 142 insertions(+), 25 deletions(-) diff --git a/gpsbabel/defs.h b/gpsbabel/defs.h index c53e5b3fb..cef56435d 100644 --- a/gpsbabel/defs.h +++ b/gpsbabel/defs.h @@ -107,6 +107,7 @@ typedef struct { geocache_container container; int diff; /* (multiplied by ten internally) */ int terr; /* (likewise) */ + time_t exported; } geocache_data ; diff --git a/gpsbabel/duplicate.c b/gpsbabel/duplicate.c index 1f29ee2d6..f2fecac93 100644 --- a/gpsbabel/duplicate.c +++ b/gpsbabel/duplicate.c @@ -142,19 +142,47 @@ free_tree (btree_node *tree) xfree(tree); } +static +int +compare(const void *a, const void *b) +{ + const waypoint *wa = *(waypoint **)a; + const waypoint *wb = *(waypoint **)b; + + if ( wa->gc_data.exported < wb->gc_data.exported ) { + return 1; + } else if ( wa->gc_data.exported > wb->gc_data.exported ) { + return -1; + } + return 0; +} + void duplicate_process(void) { - queue * elem, * tmp; waypoint * waypointp; btree_node * newnode, * btmp, * sup_tree = NULL; unsigned long crc = 0; struct { char shortname[32]; char lat[13]; char lon[13]; } dupe; waypoint * delwpt = NULL; - + + int i, ct = waypt_count(); + waypoint **htable, **bh; + queue *elem, *tmp; + extern queue waypt_head; + + htable = xmalloc(ct * sizeof(*htable)); + bh = htable; + QUEUE_FOR_EACH(&waypt_head, elem, tmp) { - waypointp = (waypoint *) elem; + *bh = (waypoint *) elem; + bh ++; + } + qsort(htable, ct, sizeof(*bh), compare); + for (i=0;iposition.altitude.altitude_meters); } - if (in_time && (in_wpt || in_rte)) { - struct tm tm; - sscanf(cdatastr, "%d-%d-%dT%d:%d:%dZ\n", - &tm.tm_year, - &tm.tm_mon, - &tm.tm_mday, - &tm.tm_hour, - &tm.tm_min, - &tm.tm_sec); - tm.tm_mon -= 1; - tm.tm_year -= 1900; - tm.tm_isdst = 1; - wpt_tmp->creation_time = mktime(&tm) + get_tz_offset(); + if (in_time) { + if ( in_wpt || in_rte) { + wpt_tmp->creation_time = + xml_parse_time( cdatastr ); + } + else { + file_time = xml_parse_time( cdatastr ); + } } if (in_wpt && in_gs_type && !in_gs_log) { wpt_tmp->gc_data.type = gs_mktype(cdatastr); @@ -466,10 +531,16 @@ gpx_end(void *data, const char *el) sscanf(cdatastr, "%f", &x); wpt_tmp->gc_data.terr = x * 10; } + if (in_gs_exported && in_wpt ) { + wpt_tmp->gc_data.exported = xml_parse_time( cdatastr ); + } in_cdata--; memset(cdatastr, 0, MY_CBUF); } if (strcmp(el, "wpt") == 0) { + if ( !wpt_tmp->gc_data.exported ) { + wpt_tmp->gc_data.exported = file_time; + } waypt_add(wpt_tmp); in_wpt--; logpoint_ct = 0; @@ -521,6 +592,9 @@ gpx_end(void *data, const char *el) in_gs_log_wpt--; in_something_else--; end_something_else(); + } else if (strcmp(el, "groundspeak:exported") == 0) { + in_gs_exported--; + /* no end_something_else because the old date is eaten */ } else if (strcmp(el, "groundspeak:travelbugs") == 0) { in_gs_tbugs--; in_something_else--; @@ -554,7 +628,7 @@ gpx_cdata(void *dta, const XML_Char *s, int len) (in_wpt && in_gs_diff) || (in_wpt && in_gs_terr) || (in_wpt && in_icon) || - (in_time && (in_wpt || in_rte))) { + (in_time)) { estr = cdatastr + strlen(cdatastr); memcpy(estr, s, len); in_cdata++; @@ -596,6 +670,8 @@ gpx_rd_init(const char *fname, const char *args) if (get_option(args, "logpoint") != NULL) opt_logpoint = 1; + file_time = 0; + psr = XML_ParserCreate(NULL); if (!psr) { fatal(MYNAME ": Cannot create XML Parser\n"); @@ -654,20 +730,22 @@ gpx_read(void) */ static void -gpx_write_time(const time_t timep) +gpx_write_time(const time_t timep, char *elname) { struct tm *tm = gmtime(&timep); if (!tm) return; - fprintf(ofd, "\n", + fprintf(ofd, "<%s>%02d-%02d-%02dT%02d:%02d:%02dZ\n", + elname, tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, - tm->tm_sec + tm->tm_sec, + elname ); } @@ -688,7 +766,7 @@ fprint_tag_and_attrs( char *prefix, char *suffix, xml_tag *tag ) } static void -fprint_xml_chain( xml_tag *tag ) +fprint_xml_chain( xml_tag *tag, const waypoint *wpt ) { char *tmp_ent; while ( tag ) { @@ -704,7 +782,12 @@ fprint_xml_chain( xml_tag *tag ) xfree(tmp_ent); } if ( tag->child ) { - fprint_xml_chain(tag->child); + fprint_xml_chain(tag->child, wpt); + } + if ( strcmp(tag->tagname, "groundspeak:cache" ) == 0 + && wpt->gc_data.exported) { + gpx_write_time( wpt->gc_data.exported, + "groundspeak:exported" ); } fprintf( ofd, "", tag->tagname); if ( tag->parentcdata ) { @@ -773,7 +856,7 @@ gpx_waypt_pr(const waypoint *waypointp) waypointp->position.altitude.altitude_meters); } if (waypointp->creation_time) { - gpx_write_time(waypointp->creation_time); + gpx_write_time(waypointp->creation_time, "time"); } if (waypointp->url) { tmp_ent = gpx_entitize(waypointp->url); @@ -791,7 +874,7 @@ gpx_waypt_pr(const waypoint *waypointp) xfree(tmp_ent); } - fprint_xml_chain( waypointp->gpx_extras); + fprint_xml_chain( waypointp->gpx_extras, waypointp ); fprintf(ofd, "\n"); } @@ -814,7 +897,7 @@ gpx_track_disp(const waypoint *waypointp) waypointp->position.latitude.degrees, waypointp->position.longitude.degrees); if (waypointp->creation_time) { - gpx_write_time(waypointp->creation_time); + gpx_write_time(waypointp->creation_time,"time"); } if (waypointp->position.altitude.altitude_meters != unknown_alt) { fprintf(ofd, "\n%f\n\n", @@ -839,6 +922,9 @@ void gpx_track_pr() void gpx_write(void) { + time_t now = 0; + + time( &now ); setshort_length(mkshort_handle, 32); fprintf(ofd, "\n"); @@ -848,6 +934,7 @@ gpx_write(void) fprintf(ofd, "xmlns=\"http://www.topografix.com/GPX/1/0\"\n"); fprintf(ofd, "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n"); + gpx_write_time( now, "time" ); switch(global_opts.objective) { case trkdata: gpx_track_pr(); case wptdata: waypt_disp_all(gpx_waypt_pr); -- 2.30.2